﻿using System;
using System.IO;
using Beaker.Specs;

namespace OpenCube.IO.Specs.Builders
{
	/// <summary>
	/// Builds a <see cref="Stream"/> that implements <see cref="Stream"/>, by appending bytes to the stream.
	/// </summary>
	[CLSCompliant(false)]
	public sealed class ByteStreamBuilder
		: Builder<Stream>
	{
		private readonly MemoryStream _stream = new MemoryStream();

		/// <summary>
		/// Append the given byte to the end of the stream.
		/// </summary>
		/// <param name="value">The byte to add to the end of the stream.</param>
		/// <returns>The <see cref="ByteStreamBuilder"/> so you can append more data.</returns>
		public ByteStreamBuilder AppendByte(byte value)
		{
			_stream.WriteByte(value);
			return this;
		}

		/// <summary>
		/// Append the given bytes to the end of the stream.
		/// </summary>
		/// <param name="bytes">The bytes to add to the end of the stream.</param>
		/// <returns>The <see cref="ByteStreamBuilder"/> so you can append more data.</returns>
		public ByteStreamBuilder AppendBytes(params byte[] bytes)
		{
			_stream.Write(bytes, 0, bytes.Length);
			return this;
		}

		/// <summary>
		/// Append the given number of random bytes to the end of the stream.
		/// </summary>
		/// <param name="count">The number of bytes to appedn to the end of the stream.</param>
		/// <returns>The <see cref="ByteStreamBuilder"/> so you can append more data.</returns>
		public ByteStreamBuilder AppendRandomBytes(int count)
		{
			for (int i = 0; i < count; i++)
				AppendByte(Some.Byte());
			return this;
		}

		/// <summary>
		/// Build a <see cref="Stream"/> holding all the data appended using the Append methods.
		/// </summary>
		/// <returns>A <see cref="Stream"/> holding all the data.</returns>
		public override Stream Build()
		{
			// clone stream and return as Stream
			byte[] buffer = _stream.ToArray();
			return new MemoryStream(buffer);
		}

	}
}